package com.fingard.dsp.bank.directbank.cdb01;

import java.util.Calendar;
import java.util.Date;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

/**
 * Description: [DSP_国开行单笔处理类]
 * Created on 19/03/07
 *
 * @author <a href="mailto:zhangxw@fingard.com.cn">ross</a>
 * @version 1.0
 * Copyright (c) 2019 FinGard
 */
public class CDB01SinglePay extends CDB01Base implements ISinglePay {
    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        //返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);
        RetAtsSglDetail tmpRetDetail;
        tmpRetDetail = d_190802(p_req1908);
        if (tmpRetDetail.respCode.equals("-1") && StringHelper.isNullOrEmpty(tmpRetDetail.reqSeqID)) {
            tmpRetDetail.reqSeqID = p_req1908.singleDetail.askNumber;
        }
        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

    //190802对外支付
    private RetAtsSglDetail d_190802(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        try {
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            CDB01Header tmpHeader = new CDB01Header();
            tmpHeader.TransCode = "STCM1001";
            tmpHeader.Fseqno = generateSeqNo(p_req1908.singleDetail.getPayDateTime(), p_req1908.singleDetail.askNumber);

            XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.autoFormat = false;
            writeCommonHeadNoReqTag(xmlWriter, tmpHeader);
            XElement tmpXElement = new XElement("Req", "");
            tmpXElement.addChild(new XElement("pay_acno", p_req1908.singleDetail.payAct));//付款账号	String(35)	M	付款账号
            tmpXElement.addChild(new XElement("pay_cur_code", convertCurToBank(p_req1908.singleDetail.payCur)));//付款币种	String(3)	M	参考7.4币种代码表（只支持人民币CNY）
            tmpXElement.addChild(new XElement("pay_acname", p_req1908.singleDetail.payName));//付款户名	String(100)	M	付款户名
            tmpXElement.addChild(new XElement("as_flag", "0"));//是否使用账簿	String(1)	M	0-不需要； 1-需要 （当多级账簿支付时使用）
            tmpXElement.addChild(new XElement("as_acno", ""));//账簿号	String(6)	C	如果AS_FLAG为1则不能为空
            tmpXElement.addChild(new XElement("as_acname", ""));//账簿名称	String(70)	C	空
            tmpXElement.addChild(new XElement("bank_flag", "1".equals(p_req1908.singleDetail.sameBnk) ? "0" : "1"));//转账类型	String(1)	M	0-行内转账 1-跨行转账
            tmpXElement.addChild(new XElement("area_flag", ""));//同城异地标志	String(1)	C	空
            tmpXElement.addChild(new XElement("urgency_flag", "1".equals(p_req1908.singleDetail.paySpd) ? "1" : "0"));//加急标志	String(1)	M	如果支付金额大于5万，不管是选择“普通”还是“加急”都走大额支付系统。 如果支付金额小于等于5万，选择“普通”，走小额支付系统；选择“加急”，走大额支付系统。  0 �C 普通; 1 �C 加急
            tmpXElement.addChild(new XElement("rcv_acno", p_req1908.singleDetail.recAct));//收款账号	String(35)	M	收款账号
            tmpXElement.addChild(new XElement("rcv_cur_code", convertCurToBank(p_req1908.singleDetail.recCur)));//收款币种	String(3)	M	参考7.4币种代码表 （只支持人民币CNY）
            tmpXElement.addChild(new XElement("rcv_acname", p_req1908.singleDetail.recName));//收款户名	String(100)	M	收款户名
            tmpXElement.addChild(new XElement("rcv_bank_no", p_req1908.singleDetail.cnapsCode));//收款行号	String(14)	C	收款人联行号
            tmpXElement.addChild(new XElement("rcv_bank_name", p_req1908.singleDetail.cnapsName));//收款行名	String(60)	C	收款行名称
            tmpXElement.addChild(new XElement("mobiles", ""));//收款方手机号码	String(11)	C	如需要短信提醒收款人，请填写
            tmpXElement.addChild(new XElement("saverecvinfo_flag", "0"));//是否保存收款方信息	String(1)	C	0-不保存； 1-保存； 保存时，可用于下次大额支付时自动补录对方联行号
            tmpXElement.addChild(new XElement("amt", p_req1908.singleDetail.payAmount));//交易金额	String(16,2)	M	交易金额
            tmpXElement.addChild(new XElement("booking_flag", "0"));//预约标志	String(1)	C	0-实时转账 1-预约转账
            tmpXElement.addChild(new XElement("booking_date", ""));//预约日期	String(8)	C	预约转账时不为空,需大于等于当前日期。 格式：YYMMDD
            tmpXElement.addChild(new XElement("booking_time", ""));//预约时间	String(6)	C	预约转账时不为空。 时间8：00-17：00 格式:HHMMSS
            tmpXElement.addChild(new XElement("purpose", p_req1908.singleDetail.purpose));
            tmpXElement.addChild(new XElement("postscript", p_req1908.singleDetail.memo));
            nodeAnalysis(p_req1908.singleDetail.srcXElement, tmpXElement, getCharset());
            xmlWriter.writeXElement(tmpXElement);
            xmlWriter.writeEndDocument();
            String[] tmpStrSignRet = sendToBank(xmlWriter.toXmlString(), true);
            if (tmpStrSignRet[0].equals(ConnState.FAIL)) {
                retDetail.respCode = "0";
                retDetail.respInfo = tmpStrSignRet[1];
                retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                retDetail.transState = PaymentState.FAIL_Payment;
                retDetail.payInfoCode = tmpStrSignRet[0];
                return retDetail;
            } else if (tmpStrSignRet[0].length() != 0) {
                retDetail.respCode = "0";
                retDetail.respInfo = "签名失败：" + tmpStrSignRet[1];
                retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                retDetail.transState = PaymentState.FAIL_Payment;
                retDetail.payInfoCode = tmpStrSignRet[0];
                return retDetail;
            }

            String afterSign = appendSignData(xmlWriter.toXmlString(), tmpStrSignRet[1]);
            String[] tmpStrRet = sendToBank(afterSign, false);
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                //解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/Packet/Data/Pub/RetCode");
                    String tmpRetMsg = tmpBkReader.getFirstText("/Packet/Data/Pub/RetMsg");
                    if ("0000".equals(tmpRetCode) || "000000".equals(tmpRetCode)) {
                        retDetail.respCode = "0";
                        retDetail.respInfo = tmpRetMsg;
                        retDetail.transState = tmpBkReader.getFirstText("/Packet/Data/Res/jnl_stat");
                        retDetail.payInfoCode = tmpBkReader.getFirstText("/Packet/Data/Res/jnl_stat");
                    } else {
                        retDetail.respCode = "-1";
                        retDetail.respInfo = tmpRetMsg;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = tmpSbMsg.toString();
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
                retDetail.respCode = "0";
                retDetail.respInfo = tmpStrRet[1];
                retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
                retDetail.transState = PaymentState.FAIL_Payment;
                retDetail.payInfoCode = tmpStrRet[0];
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpStrRet[1];
            }


        } catch (Exception ex) {
            FGBiz.limitMsg.exception(reqHeader.bankCode, ex);
            retDetail.respCode = "-1";
            retDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }
        return retDetail;
    }

    @Override
    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        RetAtsSingle retAts = d_1944_QrySglPay_WithDate(p_req1944, p_req1944.getBgnDateTime());
        if ("2218".equals(retAts.retDetail.respCode)) {
            Calendar tmpCalendarTo = Calendar.getInstance();
            tmpCalendarTo.setTime(p_req1944.getBgnDateTime());
            tmpCalendarTo.add(Calendar.DATE, 1);
            retAts = d_1944_QrySglPay_WithDate(p_req1944, tmpCalendarTo.getTime());
            if ("2218".equals(retAts.retDetail.respCode)) {
                retAts.retDetail.respCode = "0";
                retAts.retDetail.transState = "F+2218";
                retAts.retDetail.payInfoCode = "F+2218";
            }
        }
        return retAts;
    }

    private RetAtsSingle d_1944_QrySglPay_WithDate(ReqQrySingle p_req1944, Date p_QryDate) throws Exception {
//返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        retDetail.reqSeqID = p_req1944.askNumber;
        try {
            CDB01Header tmpHeader = new CDB01Header();
            tmpHeader.TransCode = "STCM1002";
            tmpHeader.Fseqno = getQryTransID();

            XmlTextWriter xmlWriter = new XmlTextWriter();
            writeCommonHead(xmlWriter, tmpHeader);
            xmlWriter.writeElementString("req_no", generateSeqNo(p_req1944.getBgnDateTime(), p_req1944.askNumber));//原交易请求号	String(40)	M	企业原交易请求流水号， 详见7.19指令包序列号编码规则
            xmlWriter.writeElementString("tr_acdt", Format.Date8Format.format(p_QryDate));//交易日期	String(8)	M	交易日期
            xmlWriter.writeElementString("qry_acno", p_req1944.payAct);//查询账号	String(35)	C	当流水类型（req_type）为"0-交易"时，该字段取值为： 多级账簿余额调整、多级账簿明细调整中的账号。 当流水类型（req_type）为"1-支付"时，该字段取值为单笔对外支付、集中代理付款和资金归集上划\下拨的付款账号；
            xmlWriter.writeElementString("req_type", "1");//流水类型	String(1)	M	0-交易；1-支付（建议采用1-支付进行流水状态查询）
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), false);
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                //解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/Packet/Data/Pub/RetCode");
                    String tmpRetMsg = tmpBkReader.getFirstText("/Packet/Data/Pub/RetMsg");
                    if ("0000".equals(tmpRetCode) || "000000".equals(tmpRetCode)) {
                        retDetail.respCode = "0";
                        retDetail.respInfo = tmpRetMsg;
                        retDetail.transState = tmpBkReader.getFirstText("/Packet/Data/Res/stat");
                        retDetail.payInfoCode = tmpBkReader.getFirstText("/Packet/Data/Res/stat");
                        retDetail.transAmt = tmpBkReader.getFirstText("/Packet/Data/Res/amt");
                    } else {
                        retDetail.respCode = tmpRetCode;
                        retDetail.respInfo = tmpRetMsg;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retDetail.respCode = "-1";
            retDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }
        retAts.writeRetDetail(retDetail);
        return retAts;
    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        return null;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        return null;
    }
}
